package Spider;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;
use encoding 'utf8';
use utf8;

use WWW::Mechanize;

use SpiderController;

#zarzadzanie intervalem
my $spiderController;

#obiekt WWW:Mechanize;
my $browser;

#obiekt WWW:Mechanize trzymajacy pobrana strone glowna wyszukiwarki
my $rootPage;

#liczba stron pobranych przez ten obiekt
my $totalPageCounter;

#dostepne wrtosci dla naglownka User-Agent
our %userAgents = (
				'IE_8'		=> 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; pl)',
				'IE_9'		=> 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
				'FIREFOX_3'	=> 'Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8',
				'FIREFOX_11'=> 'Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0',
				'CHROME_7'	=> 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7',
				'CHROME_18'	=> 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/534.7',
				'OPERA_10'	=> 'Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.6.30 Version/10.63',
				'OPERA_11'	=> 'Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.10.299 Version/11.62'
				);

#konstruktor
#klasa odpowiedzialna za pobieranie danych z jednej, zdefiniowanej wyszukiwarki 
sub new {
	shift;
	my $self = {};
	bless $self;
	
	#kontroler
	my $spiderController = SpiderController->new();
	$self->{spiderController} = $spiderController;
	
	#przygotowanie wyszukiwarki
	my $browser = private_createBrowser();
	$self->{browser} = $browser;
	
	$self->{totalPageCounter} = 1;
	
	return $self;
}

#konfiguruje robota do korzystania z wybranej wyszukiwarki
sub configure {
	my $self = shift;
	my $searcherUrl = shift;
	
	#pobranie strony glownej wyszukiwarki
	my $browser = $self->{browser};
	$browser->get($searcherUrl);
	if($browser->success()) {
		$self->{rootPage} = $browser;
	} else {
		die "Nie udało się pobrać strony " .$searcherUrl . ", błąd: " . $browser->response()->status_line . "\n";
	}
}

#tworzy i konfiguruje nowy obiekt przegladarki
sub private_createBrowser {
	my $browser = WWW::Mechanize->new();

	#podszywanie sie pod przegladarke
	my @agentsNames = keys(%userAgents);
	my $randomAgentName = $agentsNames[int(rand(scalar(@agentsNames)))];
	my $agentName = $userAgents{$randomAgentName};
	print 'Podszywam sie pod: ' . $randomAgentName; 
	
	#tablica na ew. ciasteczka
	$browser->cookie_jar({});
	
	#obsluga keep-alive
	$browser->conn_cache(LWP::ConnCache->new());
	
	#wylaczenie historii
	$browser->stack_depth(0);
	
	#wylaczenie wysylania naglowka referer
	#$browser->add_header( Referer => undef );
	
	#czas oczekiwania na odpowiedz
	$browser->timeout(30);
	
	return $browser;
}

#pobranie odpowiedzi na dana fraze
sub doQuery {
	my $self = shift;
	my $phase = shift;
	$self->{totalPageCounter}++;
	
	#utworzenie kopii strony glownej wyszukiwarki
	my $browser = $self->{rootPage};

	#zrobienie przerwy
	my $spiderController = $self->{spiderController};
	$spiderController->doInterval();
	
	#wyslanie zapytania
	$browser->form_number(1);
	
	my @textInputs = $browser->find_all_inputs(type => 'text');
	if(scalar(@textInputs) != 1) {
		die 'Liczba elementow typu input: ' . scalar(@textInputs) . 'Nie znaleziono dokladnie jednego elementu input typu text do wpisania frazy.';
	}
	my $input = $textInputs[0];
	$browser->field($input->name => $phase);
	$browser->submit();
	if($browser->success()) {
		return $browser->content(); #zwrocenie kodu html
	} else {
		die "Nie udało się otrzymać odpowiedzi na zapytanie o: " . $phase . "\n";
	}
	
	return 0;
}

#pobranie konkretnego adresu URL
sub doGet {
	my $self = shift;
	my $url = shift;
	$self->{totalPageCounter}++;
	
	#utworzenie kopii strony glownej wyszukiwarki
#	my $browser = $self->{rootPage}->clone();
	my $browser = $self->{rootPage};
	
	#zrobienie przerwy
	my $spiderController = $self->{spiderController};
	$spiderController->doInterval();
	
	#wyslanie zapytania
	$browser->get($url);
	if($browser->success()) {
		return $browser->content(); #zwrocenie kodu html
	} else {
		die "Nie udało się pobrać: $url\n";
	}
	
	return 0;
}

#zwraca liczbe stron pobranych przez ten obiekt
sub getTotalPageCounter {
	my $self = shift;
	return $self->{totalPageCounter};
}

1;